﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;

namespace Robotics.Race
{
	public class ClassLoader
	{
		static public List<string> LoadDLLFileNames( String directoryName, ICollection<string> extensions )
		{
			List<string> filenames = new List<string>();
			foreach ( string extension in extensions )
			{
				FileInfo[] files = new DirectoryInfo( directoryName ).GetFiles( "*." + extension );
				foreach ( FileInfo file in files )
				{
					filenames.Add( file.FullName );
				}
			}
			return filenames;
		}

		static public List<Type> LoadTypesFromDLLs( Type baseType, List<string> filenames )
		{
			List<Type> foundTypes = new List<Type>( 16 );
			List<Assembly> assemblies = new List<Assembly>( 16 );
			foreach ( string filename in filenames )
			{
				try
				{
					Assembly assembly = Assembly.LoadFile( filename );
					assemblies.Add( assembly );
				}
				catch ( System.Exception )
				{
				}
			}

			foreach ( Assembly assembly in assemblies )
			{
				foreach ( Type type in assembly.GetTypes() )
				{
					if ( !type.IsAbstract && baseType.IsAssignableFrom( type ) )
					{
						foundTypes.Add( type );
					}
				}
			}

			/// Filtering out base types
			List<Type> resultTypes = new List<Type>( foundTypes );
			foreach ( Type type1 in foundTypes )
			{
				foreach ( Type type2 in foundTypes )
				{
					if ( type1 != type2 )
					{
						if ( type1.IsAssignableFrom( type2 ) )
						{
							if ( resultTypes.Contains( type1 ) )
								resultTypes.Remove( type1 );
						}
					}
				}
			}

			return resultTypes;
		}
	}
}
